home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / viewkit / VCal / TimeGrid.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  11.8 KB  |  433 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <malloc.h>
  19. #include "TimeGrid.h"
  20. #include "Utils.h"
  21. #include "TimeEntry.h"
  22. #include "Preferences.h"
  23. #include <Vk/VkResource.h>
  24.  
  25. #include <Xm/LabelG.h>
  26. #include <Xm/Label.h>
  27. #include <Xm/SeparatoG.h>
  28. #include <Xm/Separator.h>
  29. #include <Xm/Form.h>
  30. #include <Xm/RowColumn.h>
  31. #include <Xm/DrawingA.h>
  32. #include <Xm/BulletinB.h>
  33.  
  34. static int count;
  35. static Arg args[10];
  36.  
  37. TimeGrid::TimeGrid(const char *name, Widget parent, Boolean editable,
  38.            int timeInterval, int subdivisions,
  39.            int start, int length)
  40. : VkComponent(name)
  41. {
  42.   _timeInt = timeInterval;
  43.   _subdiv = subdivisions;
  44.   _start = start;
  45.   _length = length;
  46.  
  47.   _marginWidth = 10;
  48.   _spacing = 10;
  49.   _width = _height = 0;
  50.   _callback = NULL;
  51.  
  52.   _start = _length = 0;
  53.   _numTime = 0;
  54.   _areas = NULL;
  55.   _textFontList = NULL;
  56.   _currentTime = NULL;
  57.   _text = NULL;
  58.  
  59.   count = 0;
  60.   XtSetArg(args[count], XmNmarginWidth, 0);  count++;
  61.   XtSetArg(args[count], XmNmarginHeight, 0);  count++;
  62.   XtSetArg(args[count], XmNallowOverlap, True);  count++;
  63.   XtSetArg(args[count], XmNshadowThickness, 0);  count++;
  64.   _baseWidget = XmCreateBulletinBoard(parent, "timeGrid", args, count);
  65.   XtAddEventHandler(_baseWidget, StructureNotifyMask, False,
  66.             TimeGrid::reconfig_stub, (XtPointer) this);
  67.   XtAddEventHandler(_baseWidget, ButtonPressMask, False,
  68.             TimeGrid::button_press, (XtPointer) this);
  69.   installDestroyHandler();
  70.  
  71.   _slotHeight = (int) VkGetResource(_baseWidget, "slotHeight", "SlotHeight",
  72.                     XmRInt, "50");
  73.  
  74.   changeDuration(start, length);
  75.  
  76.   _text = new TimeEntryText("timeGridText", this, editable);
  77.   count = 0;
  78.   XtSetArg(args[count], XmNfontList, &_textFontList);  count++;
  79.   XtGetValues(_text->baseWidget(), args, count);
  80.  
  81.   count = 0;
  82.   XtSetArg(args[count], XmNx, 0);  count++;
  83.   _currentTime = XmCreateSeparator(_baseWidget, "currentTime", args, count);
  84. }
  85.  
  86. TimeGrid::~TimeGrid()
  87. {
  88.   delete _text;
  89.   free(_areas);
  90.   if (_baseWidget) {
  91.     XtRemoveEventHandler(_baseWidget, StructureNotifyMask, False,
  92.              TimeGrid::reconfig_stub, (XtPointer) this);
  93.     XtRemoveEventHandler(_baseWidget, ButtonPressMask, False,
  94.              TimeGrid::button_press, (XtPointer) this);
  95.   }
  96. }
  97.  
  98. const char *
  99. TimeGrid::className()
  100. {
  101.   return "TimeGrid";
  102. }
  103.  
  104. /**********************************************************************/
  105.  
  106. void
  107. TimeGrid::setCallback(XtCallbackProc proc, XtPointer client_data)
  108. {
  109.   _callback = proc;
  110.   _callbackData = client_data;
  111. }
  112.  
  113. void
  114. TimeGrid::changeDuration(int start, int length)
  115. {
  116.   if (_start != start || _length != length) {
  117.     if (_areas) {
  118.       destroyAreas();
  119.       free(_areas);
  120.     }
  121.     if (_currentTime) {
  122.       XtUnmanageChild(_currentTime);
  123.     }
  124.     _start = start;
  125.     _length = length;
  126.     _numTime = (_length)/_timeInt;
  127.     _areas = (AreaInfo *) malloc(_numTime*sizeof(AreaInfo));
  128.     createAreas(_baseWidget);
  129.     count = 0;
  130.     XtSetArg(args[count], XmNheight, getHeight());  count++;
  131.     XtSetValues(_baseWidget, args, count);
  132.     XtUnmanageChild(_baseWidget);
  133.     XtManageChild(_baseWidget);
  134.     reconfig(True);
  135.   }
  136. }
  137.  
  138. Boolean
  139. TimeGrid::requestPosition(int start, int length,
  140.               Position *x_return, Position *y_return,
  141.               Dimension *width_return, Dimension *height_return)
  142. {
  143.   if (start < _start /* || start+length > _start+_length */ || !_width) {
  144.     return False;
  145.   } else {
  146.     *x_return = _marginWidth+_maxWidth+_spacing+_leftW;
  147.     *y_return = ((start-_start)*_slotHeight*_subdiv)/_timeInt+_sepH;
  148.     *width_return = _width-2*_marginWidth-_maxWidth-_leftW-_rightW-_spacing;
  149.     *height_return = (length*_slotHeight*_subdiv)/_timeInt-_sepH;
  150.  
  151.     return True;
  152.   }
  153. }
  154.      
  155. Boolean
  156. TimeGrid::requestWeekdayPosition(int start, int length, int weekday,
  157.                  Position *x_return, Position *y_return,
  158.                  Dimension *width_return,
  159.                  Dimension *height_return)
  160. {
  161.   Dimension offset;
  162.  
  163.   if (requestPosition(start, length, x_return, y_return,
  164.               width_return, height_return)) {
  165.     offset = (*width_return)/DAYS_IN_WEEK;
  166.     *x_return = (*x_return)+(weekday-1)*offset;
  167.     *width_return = offset;
  168.     return True;
  169.   } else {
  170.     return False;
  171.   }
  172. }
  173.      
  174. Boolean
  175. TimeGrid::requestIntervalPosition(int start, int length,
  176.                   Position *x_return, Position *y_return,
  177.                   Dimension *width_return,
  178.                   Dimension *height_return)
  179. {
  180.   if (start < _start /* || start+length > _start+_length */ || !_width) {
  181.     return False;
  182.   } else {
  183.     *x_return = _marginWidth;
  184.     *y_return = ((start-_start)*_slotHeight*_subdiv)/_timeInt+_sepH;
  185.     *width_return = _maxWidth+_spacing;
  186.     *height_return = (length*_slotHeight*_subdiv)/_timeInt-_sepH;
  187.  
  188.     return True;
  189.   }
  190. }
  191.      
  192. void
  193. TimeGrid::requestInterval(Position y, Dimension height,
  194.               int *start_return, int *length_return)
  195. {
  196.   *start_return = ((y-_sepH)*_timeInt)/_slotHeight/_subdiv;
  197.   *start_return = *start_return-(*start_return % (_timeInt/_subdiv))+_start;
  198.   *length_return = ((height+_sepH)*_timeInt)/_slotHeight/_subdiv;
  199. }
  200.  
  201. void
  202. TimeGrid::reconfig(Boolean always)
  203. {
  204.   Dimension width, height;
  205.   int each;
  206.  
  207.   count = 0;
  208.   XtSetArg(args[count], XmNwidth, &width);  count++;
  209.   XtSetArg(args[count], XmNheight, &height);  count++;
  210.   XtGetValues(_baseWidget, args, count);
  211.   if (always || width != _width || height != _height) {
  212.     _width = width;
  213.     _height = height;
  214.     count = 0;
  215.     XtSetArg(args[count], XmNwidth, &_leftW);  count++;
  216.     XtGetValues(_left, args, count);
  217.     count = 0;
  218.     XtSetArg(args[count], XmNwidth, &_rightW);  count++;
  219.     XtGetValues(_right, args, count);
  220.     count = 0;
  221.     XtSetArg(args[count], XmNheight, &_sepH);  count++;
  222.     XtGetValues(_areas[0].separator, args, count);
  223.     
  224.     count = 0;
  225.     XtSetArg(args[count], XmNwidth, _width-2*_marginWidth);  count++;
  226.     XtSetValues(_bottom, args, count);
  227.     for (each=0; each<_numTime; each++) {
  228.       XtSetValues(_areas[each].separator, args, count);
  229.     }
  230.     count = 0;
  231.     XtSetArg(args[count], XmNheight, getHeight());  count++;
  232.     XtSetValues(_left, args, count); 
  233.     count = 0;
  234.     XtSetArg(args[count], XmNx, _width-_marginWidth-_rightW);  count++;
  235.     XtSetArg(args[count], XmNheight, getHeight());  count++;
  236.     XtSetValues(_right, args, count);
  237.     if (_text) {
  238.       _text->reposition();
  239.     }
  240.     if (_currentTime) {
  241.       count = 0;
  242.       XtSetArg(args[count], XmNwidth, width);  count++;
  243.       XtSetValues(_currentTime, args, count);
  244.     }
  245.   }
  246. }
  247.  
  248. void
  249. TimeGrid::reset()
  250. {
  251.   _text->hide();
  252.   _text->setCallback(NULL, NULL);
  253. }
  254.  
  255. void
  256. TimeGrid::hideCurrentTime()
  257. {
  258.   if (_currentTime) {
  259.     XtUnmanageChild(_currentTime);
  260.   }
  261. }
  262.  
  263. void
  264. TimeGrid::showCurrentTime(int start)
  265. {
  266.   Position y, ignore_p;
  267.   Dimension ignore_d;
  268.  
  269.   if (_currentTime) {
  270.     if (requestPosition(start, 0, &ignore_p, &y, &ignore_d, &ignore_d)) {
  271.       count = 0;
  272.       XtSetArg(args[count], XmNy, y);  count++;
  273.       XtSetValues(_currentTime, args, count);
  274.       XtManageChild(_currentTime);
  275.       if (XtWindow(_currentTime)) {
  276.     XRaiseWindow(XtDisplay(_currentTime), XtWindow(_currentTime));
  277.       }
  278.     } else {
  279.       hideCurrentTime();
  280.     }
  281.   }
  282. }
  283.  
  284. /**********************************************************************/
  285.  
  286. void
  287. TimeGrid::createAreas(Widget parent)
  288. {
  289.   int each;
  290.   char str[256];
  291.   XmString xs;
  292.   Dimension width;
  293.  
  294. // Vertical separators
  295.   count = 0;
  296.   XtSetArg(args[count], XmNx, 0);  count++;
  297.   XtSetArg(args[count], XmNy, 0);  count++;
  298.   XtSetArg(args[count], XmNorientation, XmVERTICAL);  count++;
  299.   _right = XmCreateSeparatorGadget(parent, "rightSeparator", args, count);
  300.   XtManageChild(_right);
  301.   count = 0;
  302.   XtSetArg(args[count], XmNx, 0);  count++;
  303.   XtSetArg(args[count], XmNy, 0);  count++;
  304.   XtSetArg(args[count], XmNorientation, XmVERTICAL);  count++;
  305.   _left = XmCreateSeparatorGadget(parent, "leftSeparator", args, count);
  306.   XtManageChild(_left);
  307.  
  308. // Separators and time labels
  309.   for (each=0; each<_numTime; each++) {
  310.     count = 0;
  311.     XtSetArg(args[count], XmNx, _marginWidth);  count++;
  312.     XtSetArg(args[count], XmNy,
  313.          each*_subdiv*_slotHeight);  count++;
  314.     XtSetArg(args[count], XmNorientation, XmHORIZONTAL);  count++;
  315.     _areas[each].separator = XmCreateSeparatorGadget(parent, "separator",
  316.                              args, count);
  317.     count = 0;
  318.     XtSetArg(args[count], XmNheight, &_horizSepHeight);  count++;
  319.     XtGetValues(_areas[each].separator, args, count);
  320.  
  321.     formatTime((_start+each*_timeInt) / 60, (_start+each*_timeInt) % 60,
  322.            thePreferences->clock24(), str);
  323.     xs = XmStringCreateSimple(str);
  324.     count = 0;
  325.     XtSetArg(args[count], XmNx, _marginWidth);  count++;
  326.     XtSetArg(args[count], XmNy,
  327.          each*_subdiv*_slotHeight+_horizSepHeight);  count++;
  328.     XtSetArg(args[count], XmNalignment, XmALIGNMENT_END);  count++;
  329.     XtSetArg(args[count], XmNrecomputeSize, False);  count++;
  330.     XtSetArg(args[count], XmNlabelString, xs);  count++;
  331.     _areas[each].timeLabel = XmCreateLabel(parent, "timeLabel",
  332.                        args, count);
  333.     XtAddEventHandler(_areas[each].timeLabel, ButtonPressMask, False,
  334.               TimeGrid::button_press, (XtPointer) this);
  335.     XmStringFree(xs);
  336.  
  337.     XtManageChild(_areas[each].separator);
  338.     XtManageChild(_areas[each].timeLabel);
  339.   }
  340.  
  341. // Make the time labels right-aligned
  342.   _maxWidth = 0;
  343.   count = 0;
  344.   XtSetArg(args[count], XmNwidth, &width);  count++;
  345.   for (each=0; each<_numTime; each++) {
  346.     XtGetValues(_areas[each].timeLabel, args, count);
  347.     if (width > _maxWidth) {
  348.       _maxWidth = width;
  349.     }
  350.   }
  351.   count = 0;
  352.   XtSetArg(args[count], XmNwidth, _maxWidth);  count++;
  353.   for (each=0; each<_numTime; each++) {
  354.     XtSetValues(_areas[each].timeLabel, args, count);
  355.   }
  356.  
  357. // Move the left separator over
  358.   count = 0;
  359.   XtSetArg(args[count], XmNx, _marginWidth+_maxWidth+_spacing);  count++;
  360.   XtSetValues(_left, args, count);
  361.  
  362. // Bottom separator
  363.   count = 0;
  364.   XtSetArg(args[count], XmNx, _marginWidth);  count++;
  365.   XtSetArg(args[count], XmNy,
  366.        _numTime*_subdiv*_slotHeight+_horizSepHeight);  count++;
  367.   XtSetArg(args[count], XmNorientation, XmHORIZONTAL);  count++;
  368.   _bottom = XmCreateSeparatorGadget(parent, "bottomSeparator", args, count);
  369.   XtManageChild(_bottom);
  370. }
  371.  
  372. void
  373. TimeGrid::destroyAreas()
  374. {
  375.   int each;
  376.  
  377.   XtDestroyWidget(_right);
  378.   XtDestroyWidget(_left);
  379.   XtDestroyWidget(_bottom);
  380.   for (each=0; each<_numTime; each++) {
  381.     XtDestroyWidget(_areas[each].separator);
  382.     XtDestroyWidget(_areas[each].timeLabel);
  383.   }
  384. }
  385.  
  386. void
  387. TimeGrid::callCallback(TimeGridReason reason, int value, void *d)
  388. {
  389.   TimeGridCallback data;
  390.  
  391.   if (_callback) {
  392.     data.reason = reason;
  393.     data.value = value;
  394.     data.data = d;
  395.     (*_callback)(_baseWidget, _callbackData, (XtPointer) &data);
  396.   }
  397. }
  398.  
  399. void
  400. TimeGrid::buttonPress(XEvent *event)
  401. {
  402.   int start, ignore;
  403.  
  404.   if (event->xbutton.button == Button1) {
  405.     if (event->xbutton.x < _marginWidth+_maxWidth+_spacing ||
  406.     event->xbutton.x >= _width-_marginWidth) {
  407.       callCallback(TG_deselect);
  408.     } else {
  409.       requestInterval(event->xbutton.y, 0, &start, &ignore);
  410.       callCallback(TG_requestNew, start, event);
  411.     }
  412.   }
  413. }
  414.  
  415. /**********************************************************************/
  416.  
  417. void
  418. TimeGrid::reconfig_stub(Widget, XtPointer client_data, XEvent *, Boolean *)
  419. {
  420.   TimeGrid *obj = (TimeGrid *) client_data;
  421.  
  422.   obj->reconfig();
  423. }
  424.  
  425. void
  426. TimeGrid::button_press(Widget, XtPointer client_data, XEvent *event, Boolean *)
  427. {
  428.   TimeGrid *obj = (TimeGrid *) client_data;
  429.  
  430.   obj->buttonPress(event);
  431. }
  432.  
  433.